<?php defined('BASEPATH') OR exit('No direct script access allowed');
/**
 * Description: 添加接口
 *
 * @author      Eden
 * @datetime    2016/12/1 22:56
 * @copyright   Beijing CmsTop Technology Co.,Ltd.
 */

class Add2_Model extends API_Model
{

    // 参数
    private $params;

    private $uuid;

    private $return = array();

    private $errorData = array();

    private $user = [];

    // 代金券等额面值
    private $voucherPrice = 0;

    // 商品总重量
    private $baseGoods = [];

    private $userType = 0;

    /**
     * 初始化
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * 主程序
     * @param array $params
     */
    public function run(Array $params) {
        $this->params = $params;
        $send['state'] = false;
        do {

            $this->userType = $this->getUserType(value($params, 'userId'));
            if (!$this->_checkParams() || !$this->checkGoods() || !$this->checkAddress()) {
                $send['error'] = $this->getError() ? $this->getError() : '下单失败';

                if (!empty($this->errorData)) {
                    $send['error'] = $this->errorData;
                }
                break;
            }

            if (!$this->addOrder()) {
                $send['error'] = $this->getError() ? $this->getError() : '下单失败';
                break;
            }

            @statIncr('appOrders');

            $send['state'] = true;
            $send['data'] = $this->return;

        } while(false);
        $this->output->send($send);
    }

    /**
     * 执行添加操作
     * @return bool
     */
    private function addOrder()
    {
        $nowDate = dateTime();

        try {
            $this->db->trans_start();

            $this->load->model('common/ExpressPrice_Model', 'e');
            $exp = $this->e->price($this->params['userId']);
            $uuid = sn();

            $payMode = value($this->params, 'payMode', 'online');
            $baseExp = $exp['base'];
            foreach ($this->baseGoods as $baseId => $item) {

                if (!isset($baseExp[$baseId])) {
                    $this->setError('未知错误');
                    return false;
                }

                $goodsData = [];
                $baseGoodsPrice = 0;
                foreach ($item as $i) {
                    $baseGoodsPrice += intval($i['price']) * $i['num'];
                }

                $sn = sn();
                $userOrderData = array(
                    'uuid' => $uuid,
                    'sn' => $sn,
                    'userId' => $this->params['userId'],
                    'baseId' => $baseId,
                    'priceType' => $this->getUserType($this->params['userId']),
                    'addressId' => $this->params['addressId'],
                    'payMode' => $payMode,
                    'totalPrice' => $baseGoodsPrice + $baseExp[$baseId],
                    'goodsPrice' => $baseGoodsPrice,
                    'expressPrice' => $baseExp[$baseId],
                    'voucherPrice' => 0,
                    'status' => $payMode == 'online' ? 'Unpaid' : 'Pending',
                    'message' => value($this->params, 'message', ''),
                    'voucher' => empty($this->params['voucher']) ? '' : $this->params['voucher'],
                    'created' => $nowDate,
                    'merge' => $payMode == 'online' ? 1 : 0,
                );

                $oDb = clone($this->db);
                $oDb->insert('user_order', $userOrderData);
                $orderId = $oDb->insert_id();

                if (empty($orderId)) {
                    $this->setError('下单失败');
                    return false;
                }

                foreach ($item as $i) {
                    $goodsData[] = array(
                        'orderId' => $orderId,
                        'goodsId' => $i['goodsId'],
                        'num' => $i['num'],
                        'price' => $i['price'],
                        'ruleId' => $i['ruleId']
                    );
                }

                if (empty($goodsData)) {
                    $this->setError('下单失败');
                    return false;
                }

                $uogDb = clone($this->db);
                $uogDb->insert_batch('user_order_goods', $goodsData);

                // 更新 car 表
                $this->updateCars($goodsData);
                $this->db->trans_complete();
                if ($this->db->trans_status() === false) {
                    $this->setError('下单失败');
                    return false;
                }
            }

            $this->uuid = $uuid;
            $this->return = [
                'sn' => $uuid,
                'userId' => $this->params['userId'],
                'payMode' => $payMode
            ];

            return true;
        } catch(PDOException $e) {
            $this->setError('下单失败');
            return false;
        }
    }

    /**
     * 删除购物里里已经购买过的商品
     * @param array $goodsData
     */
    private function updateCars(Array $goodsData)
    {
        $db = clone($this->db);
        $goodsIds = [];
        foreach ($goodsData as $good) {
            $goodsIds[] = $good['goodsId'];
        }
        $db->where_in('goodsId', $goodsIds);
        $db->where('userId', $this->params['userId']);
        $db->delete('user_car');
        return $db->affected_rows();
    }

    /**
     * 检查前后台的价格
     * @param int $totalGoodsPrice
     * @param int $totalWeight
     * @return bool
     */
    private function checkPrice($totalGoodsPrice = 0, $totalWeight = 0)
    {
        $totalPrice = doubleval($this->params['totalPrice']);
        $goodsPrice = doubleval($this->params['goodsPrice']);
        $expressPrice = doubleval($this->params['expressPrice']);

        if ($totalWeight == 0 && $expressPrice == 0) {
            return true;
        }

        // 对比商品金额
        if (bccomp($goodsPrice, $totalGoodsPrice, 2) !== 0) {
            $this->setError('商品金额不符');
            return false;
        }

        $expressCosts = $this->getExpressCosts($totalWeight);
        if (bccomp($expressPrice, $expressCosts, 2) !== 0) {
            $this->setError('运费金额不符');
            return false;
        }

        // 对比用代金券后的金额
        $total = $goodsPrice + $expressCosts;
        if (!empty($this->params['voucher'])) {
            $total += $this->voucherPrice;
            if (bccomp($total, $totalPrice, 2) !== 0) {
                $this->setError('总金额有误');
                return false;
            }
        } else {
            if (bccomp($total, $totalPrice, 2) !== 0) {
                $this->setError('总金额有误');
                return false;
            }
        }
        return true;
    }

    /**
     * 计算运费
     * @param int $totalWeight
     * @return float|int
     */
    private function getExpressCosts($totalWeight = 0)
    {
        if ($totalWeight == 0) {
            return 0;
        }

        $config = $this->_getShippingCosts();
        if ($config['payer'] == 'buyer') {
            $costs = $config['costs'];
            $firstWeight = $costs['firstWeight'];
            $firstCost = $costs['firstCost'];
            $incrWeight = $costs['incrWeight'];
            $incrCost = $costs['incrCost'];
            if ($firstWeight >= $totalWeight) {
                return $firstCost;
            } else {
                $left = $totalWeight - $firstWeight;
                return ceil($left / $incrWeight) * $incrCost + $firstCost;
            }

        } else {
            return 0;
        }
    }

    /**
     * 获取跟客户端一样的物流配置
     * @return array
     */
    private function _getShippingCosts()
    {
        $default = array(
            'payer' => 'seller',
            'costs' => []
        );
        // 前期只考虑到统一的价格的情况,没有进行区域区分
        $db = clone($this->db);
        $q = $db->get_where('express_template', array('using' => 1));
        $row = $q->row_array();
        if (!$row) {
            return $default;
        }

        if ($row['payer'] == 'seller') {
            return $default;
        }

        $payer = $row['payer'];
        if ($row['payType'] == 'weight') {
            $q = $this->db->get_where('express_weight', array('tmpId' => $row['id']));
            $row = $q->row_array();
            if (empty($row)) {
                return $default;
            }
            $default['payer'] = $payer;
            $default['costs'] = array(
                'firstWeight' => doubleval($row['firstWeight']),
                'firstCost' => doubleval($row['firstCost']),
                'incrWeight' => doubleval($row['incrWeight']),
                'incrCost' => doubleval($row['incrCost'])
            );
        }

        return $default;
    }

    /**
     * @return bool
     */
    private function checkAddress()
    {
        try {
            $addDb = clone($this->db);
            $query = $addDb->get_where('user_address', array(
                'id' => $this->params['addressId'],
                'userId' => $this->params['userId']
            ));
            $address = $query->row_array();
            if (empty($address)) {
                $this->setError('用户地址不存在');
                return false;
            }
            return true;
        } catch (PDOException $e) {}
        return false;
    }

    /**
     * 检查商品是否存在
     * @return bool
     */
    private function checkGoods()
    {
        $goods = $this->getCarGoods();
        if (empty($goods)) {
            $this->setError('您还没有添加商品');
            return false;
        }

        // 商品
        $totalPrice = 0;
        $tmp = [];
        foreach ($goods as $item) {
            if ($item['num'] > $item['stock']) {
                $this->setError('部分商品库存不足');
                return false;
            }

            if ($item['status'] == 0) {
                $this->setError('含有下架商品');
                return false;
            }

            $totalPrice += intval($item['price']) * $item['num'];
            $tmp[$item['baseId']][] = $item;
        }

        $this->baseGoods = $tmp;
        return true;
    }

    /**
     * 商品
     * @return array
     */
    private function getCarGoods()
    {
        $where = ['c.userId' => $this->params['userId'], 'c.selected' => 1];
        $db = clone($this->db);
        $q = $db->select('g.id as goodsId, g.baseId, g.status, c.num, c.selected, r.id as ruleId, r.name as ruleName, 
        r.stock, r.salePrice, r.purchaserPrice')
            ->from('user_car as c')
            ->join('base_goods as g', 'g.id = c.goodsId')
            ->join('base_goods_rule as r', 'r.id=c.ruleId')
            ->order_by('c.created', 'DESC')
            ->where($where)
            ->get();
        $rows = $q->result_array();

        if (empty($rows)) {
            return [];
        }

        $returns = array();
        foreach($rows as $item) {
            $price = $this->userType == 1 ? intval($item['purchaserPrice']) : intval($item['salePrice']);
            $returns[] = array(
                'goodsId' => intval($item['goodsId']),
                'baseId' => intval($item['baseId']),
                'stock' => intval($item['stock']),
                'price' => $price,
                'status' => $item['status'],
                'num' => intval($item['num']),
                'ruleId' => $item['ruleId'],
                'selected' => intval($item['selected'])
            );
        }
        return $returns;
    }

    /**
     * 检查参数
     * @return bool
     */
    private function _checkParams()
    {

        if ($this->input->method(true) !== 'POST') {
            //$this->setError('非法请求');
            //return false;
        }

        $needs = array('userId', 'addressId', 'payMode');
        foreach ($needs as $field) {
            if (!array_key_exists($field, $this->params) || empty($this->params[$field])) {
                $this->setError('参数错误');
                return false;
            }
        }

        if (!in_array($this->params['payMode'], array('online', 'delivery'))) {
            $this->setError('不支持的支付方式');
            return false;
        }

        if (!empty($this->params['voucher']) && !$this->checkVoucher($this->params['userId'], $this->params['voucher'])) {
            return false;
        }

        if (!empty($this->params['balance']) && !$this->checkBalance($this->params['userId'], $this->params['balance'])) {
            return false;
        }

        return true;
    }

    /**
     * 检查用户余额
     * @param $userid
     * @param int $balance
     * @return bool
     */
    function checkBalance($userid, $balance = 0)
    {
        $db = clone($this->db);
        $q = $db->get_where('user', ['id' => $userid]);
        $row = $q->row_array();
        if (empty($row)) {
            return false;
        }

        if ($row['amountUnLimit'] < $balance) {
            return false;
        }

        $this->user = $row;

        return true;
    }

    /**
     * 代金券
     * @param $userId
     * @param string $voucher
     * @return bool
     */
    private function checkVoucher($userId, $voucher = '')
    {
        $db = clone($this->db);
        $q = $db->get_where('user_voucher', array('userId' => $userId, 'status' => 1, 'voucher' => $voucher));
        $row = $q->row_array();
        if (empty($row)) {
            $this->setError('无效的代金券');
            return false;
        }

        $expires = strtotime($row['expires']);
        if ($expires < time()) {
            $this->setError('代金券已过期');
            return false;
        }

        if ($row['used'] != 1) {
            $this->setError('代金券已被使用');
            return false;
        }

        $this->voucherPrice = doubleval($row['price']);

        return true;
    }
}